
import logging

from freebase.api import HTTPMetawebSession, MetawebError
import simplejson


class FreebaseError(Exception):
     def __init__(self, value):
         self.value = value
         
     def __str__(self):
         return repr(self.value)


class FreebaseSession(object):
    def __init__(self, url, username=None, password=None):
        self._session = HTTPMetawebSession(url, username=username, password=password)
        self._logged_in = False
        
    def mqlread(query):
        return self._session.mqlread(query)
    
    def _check_login(self):
        if not self._logged_in:
            self._logged_in = True
            self._session.login()
    
    def get_topic(self, name):
        """ Returns a Freebase object that has the name provided, 
        or creates a new object.
        """
        self._check_login()
        query = [{    
          "create": "unless_exists",
          "type": "/common/topic",
          "name": name,
          "id": None
        }]
        result = self._session.mqlwrite(query)
        print 'get_object: '
        self.log_data(result)
        if len(result) > 1:
            raise FreebaseError('Too many objects')
        return Topic(self, data=result[0])
    
    def get_type(self, id):
        """
        """
        self._check_login()
        query = [{
            'id': id,
            '*': None,
            "properties":[{
                "expected_type":{
                  "default_property": None,
                  "id": None,
                  "key": None,
                  "name": None,
                },
                "name": None,
            }],
            "type":"/type/type"
        }]
        result = self._session.mqlread(query)
        self.log_data(result)
        if len(result) != 1:
            raise FreebaseError('Type could not be found')
        return Type(self, data=result[0])
        
    @staticmethod
    def log_data(data):
        print simplejson.dumps(data, sort_keys=True, indent=4)


class FreebaseObject(object):
    """ Base class for all Freebase objects. """
    
    def __init__(self, session, data=None):
        self.__dict__['session'] = session
        self.__dict__['writes'] = []
        if data != None:
            self.__dict__['data'] = data
        
    def __getattr__(self, name):
        print '__getattr__: ' + name
        data = self.__dict__['data']
#        print data.keys()
        return data[name]
    
    def __setattr__(self, name, value):
        print '__setattr__: ' + name + ' ' + value
        if not name in self.__dict__:
            raise AttributeError('Invalid property for Freebase object.')
        self.__dict__[name] = value
        
    def data(self):
        """ Return the raw Freebase object data. """
        self.__dict__['data']
    
    def read(self):
        #query = [{'query': self.data()}]
        query = self.data()
        query['*'] = None
        #query[0]['query']['guid'] = None
        print query
        print self.session.mqlread(query)
        
    def add_write(self, write_query):
        self.writes.append(write_query)
        
    def write(self):
        self.session.mqlwrite(query)
        
    def __str__(self):
        str = ''
        if self.name != None:
            str = self.name
        elif self.id != None:
            str = self.id
        return str
    
    def __repr__(self):
        return self.__str__()

        
class Topic(FreebaseObject):
    """ A Freebase topic. """
    
    def __init__(self, session, data=None):
        FreebaseObject.__init__(self, session, data=data)
        
    def add_type(self, type_id):
        query = {"type":{
            "connect":"insert",
            "id": type_id
          }}
        self.add_write(query)
        
        
class Type(FreebaseObject):
    """ A Freebase type. """
    
    def __init__(self, session, data=None):
        FreebaseObject.__init__(self, session, data=data)
        
    @staticmethod
    def create(session, data):
        type = Type(session, data['id'])
        return type
    
    def topics(self):
        query = [{    
          'type': self.id,
          '*': None,
          }]
        result = self.session.mqlread(query)
        topics = []
        for item in result:
            if item['source']['type'][0] == '/type/type':
                topics.append(Topic.create(self.session, item['source']))
        return topics
        
        
class Base(FreebaseObject):
    """ A Freebase Base. """
    
    def __init__(self, session, id):
        FreebaseObject.__init__(self, session)
        self.id = id
    
    def types(self):
        query = [{    
          "type": "/type/link",
          "target": {
            "id": "/base/seafood"
          },
          "source": {}
          }]
        result = self.session.mqlread(query)
        #return simplejson.dumps(result, sort_keys=True, indent=4)
        types = []
        for item in result:
            if item['source']['type'][0] == '/type/type':
                types.append(Type.create(self.session, item['source']))
        return types
        
        

